;(function($) {
    var $cache = {};
    var $dialogToRelPositionElement = {};

    var methods = {
        //Note: Should only run axDialog on a div once it is in the actual DOM
        init : function( ) {
            var $dialogParentDiv = $(this).parent();
            var $thisDiv = $(this);
            var thisDivIdOrClass = $thisDiv.attr('id') || ($thisDiv.attr('class').split(' '))[0];

            if($dialogParentDiv.find('#' + thisDivIdOrClass + 'Overlay').length == 0){
                var $overlay = $('<div id="' + thisDivIdOrClass + 'Overlay">').addClass('dialogOverlay').appendTo($dialogParentDiv);

                var overlayCssSettings = {
                    //'background' : '#FFF',
                    'background' : 'rgba(0, 0, 0, 0.6)',
                    //'filter' : 'alpha(opacity=70)',
                    //'opacity' : '0.7',
                    'display' : 'none',
                    'position' : 'absolute',
                    'top' : '0px',
                    'left' : '0px',
                    'width' : '100%',
                    'height' : '100%',
                    'z-index' : '100',
                    'cursor' : 'pointer'
                };

                $overlay.css(overlayCssSettings);

                $overlay.click(function() {
                    var $dialogLoadImage = $thisDiv.find('.dialogLoadingImage');
                    if ($dialogLoadImage.length == 0 || !($dialogLoadImage.is(":visible"))) {
                        $thisDiv.axDialog('hide');
                    }
                });
            }
            return this;
        },
        show : function( ) {
            if($cache['currDialog'] != null) return this;
            $cache['currDialog'] = this;

            //If the relative position element for this dialog hasn't been stored yet,
            //find it and store it (for use in update function)
            if(!$dialogToRelPositionElement[this])
            {
                //This finds the first parent of the dialog that contains a 
                //non-static value for the css position, as the dialog is positioned
                //relative to it.
                var positionContainer = this.parents().filter(function() {
                    var position = $(this).css('position');

                    if(position.length > 0 && position != 'static'){
                        return true;
                    }
                
                    return false;
                }).eq(0);

                //If no parent dialog with non-static position was found, then
                //the dialog is positioned relative to the whole window.
                if(positionContainer.length == 0){
                    positionContainer = $(window);
                }
                //Store in local cache for use in update function
                $dialogToRelPositionElement[this] = positionContainer;
            }

            (methods.update)();

            var thisDivIdOrClass = $(this).attr('id') || ($(this).attr('class').split(' '))[0];
            $('#' + thisDivIdOrClass + 'Overlay').show(0.2);
            this.show(0.2);

            return this;
        },
        hide : function( ) {
            if($cache['currDialog'] == null) return this;
            if(this.length == 0) return this; 

            //Check for equality of this jQuery and cached dialog to make
            //sure they contain the same set of elements
            for (var i = 0; i < this.length; ++i) {
                if (this[i] !== ($cache['currDialog'])[i]) {
                  return this;
                }
            }

            $cache['currDialog'] = null;
            var thisDivIdOrClass = $(this).attr('id') || ($(this).attr('class').split(' '))[0];
            $('#' + thisDivIdOrClass + 'Overlay').hide(0.2);
            this.hide(0.2);  

            return this;
        },
        update : function( ) {
            if ($cache['currDialog'] == null) return;
            // set the overlay size
            var doc = $(document);
            $('.dialogOverlay')
                .height(doc.height())
                .width(doc.width());

            // set the dialog location
            var dialog = $cache['currDialog'];
            // Get the element that the dialog is positioned relative to
            var relativePositionElement = $dialogToRelPositionElement[dialog];

            var dlgX = relativePositionElement.scrollLeft() + (relativePositionElement.width() - dialog.outerWidth()) / 2;
            var dlgY = relativePositionElement.scrollTop() + (relativePositionElement.height() - dialog.outerHeight()) / 2;

            dlgX = Math.max(dlgX, 0);
            dlgY = Math.max(dlgY, 0);

            dialog.css({ left: dlgX, top: dlgY });
        }
    };

    $(window).bind('resize.axDialog', methods.update);
    $(document).keyup(function(e) {
        if (e.keyCode == 27) {
            if ($cache['currDialog'] == null) return;

            var $dialogLoadImage = $cache['currDialog'].find('.dialogLoadingImage');
            if ($dialogLoadImage.length == 0 || !($dialogLoadImage.is(":visible"))) {
                $cache['currDialog'].axDialog('hide');
            }
        }
    });

    $.fn.axDialog = function( method ) {
        // Method calling logic
        if ( methods[method] ) {
            return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.axDialog' );
        }    
    };
})(jQuery);